package com.szholly.plug.safe.entity.role;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.szholly.utils.session.SessionFactory;
import com.szholly.utils.session.provider.ISessionProvider;
import com.szholly.utils.util.TreeDataNode;
import com.szholly.data.common.util.TreeDataUtils;
import com.szholly.data.general.*;
import com.szholly.plug.safe.core.SafeCache;
import com.szholly.plug.safe.entity.fun.DataFunctionEntity;
import com.szholly.plug.safe.entity.fun.DataFunctionItemEntity;
import com.szholly.plug.safe.entity.fun.DataFunctionItemService;
import com.szholly.plug.safe.entity.fun.DataFunctionService;
import com.szholly.plug.safe.entity.fun.FunctionEntity;
import com.szholly.plug.safe.entity.fun.FunctionService;
import com.szholly.plug.safe.entity.user.UserEntity;
import com.szholly.plug.safe.entity.user.UserRoleEntity;
import com.szholly.plug.safe.entity.user.UserRoleService;
import com.szholly.plug.safe.entity.user.UserService;

/**
 * 定义用户角色权限辅助类
 */
public class RoleInitHelper {
	
	private static Logger logger = Logger.getLogger(RoleInitHelper.class);

	/**
	 * 初始化用户角色数据
	 */
	public static void InitRoleData() {
		initFunctionData();
		initWtData();
		initSQLData();
	}
	
	/**
	 * 重新初始化用户角色数据
	 * 但不初始化角色委托数据
	 */
	public static void ReInitRoleData() {
		// 用户与用户角色不缓存，角色与功能之间的数据变化了，才需要清除缓存
		SafeCache.setFunctionCache(null);
		SafeCache.setRoleFunctionCache(null);
		SafeCache.setRoleSqlCache(null);
		// 因为数据已经在角色委托中已经解决
		// SafeCache.setRoleWTCache(null);
		
		InitRoleData();
	}
	
	/**
	 * 重新初始化角色委托数据
	 */
	public static void ReInitWtRoleData() {
		// 用户与用户角色不缓存，角色与功能之间的数据变化了，才需要清除缓存
		SafeCache.setRoleWTCache(null);
		
		initWtData();
	}

	/**
	 * 初始化角色数据权限数
	 */
	private static void initSQLData() {
		try {
			HashMap<String, HashMap<String, String>> sqlCache = SafeCache.getRoleSqlCache();
			// 如果缓存存在，就说明已经初始过了，不需要再初始化
			if (sqlCache != null) {
				return;
			}
			logger.info("initSQLData 初始化角色数据权限数据");
			
			// 获取SQL数据权限定义
			List<RowBase> rowList = 
					DataFunctionService.getSingleRef().getEntityList(RowBase.class, new QueryMap());
			List<TreeDataNode> nodeList = TreeDataUtils.GetTreeData(rowList, 
					DataFunctionEntity.FIELD_FUNCTIONID, DataFunctionEntity.FIELD_PID, 
					DataFunctionEntity.FIELD_FUNCTIONID, DataFunctionEntity.FIELD_DOMAINNAME);
			
			List<DataFunctionItemEntity> functionItemList = 
					DataFunctionItemService.getSingleRef().getEntityList(DataFunctionItemEntity.class, new QueryMap());
			// functionid, tableid, where
			HashMap<String, HashMap<String, String>> functionMap = new HashMap<String, HashMap<String, String>>();
			if(functionItemList!=null){
				for(DataFunctionItemEntity item : functionItemList){
					String functionId = item.getFunctionID();
					String tableId = item.getTableName();
					tableId = tableId.toUpperCase().trim();
					String tableWhere = item.getTableWhere();
					
					HashMap<String, String> map = null;
					if(functionMap.containsKey(functionId)){
						map = functionMap.get(functionId);
					}else{
						map = new HashMap<String, String>();
						functionMap.put(functionId, map);
					}
					
					if(map.containsKey(tableId)){
						tableWhere = "(" + map.get(tableId) + ") and ( " + tableWhere + " )";
						map.put(tableId, tableWhere);
					}else{
						map.put(tableId, tableWhere);
					}
				}
			}

			// 获取角色与数据权限间的关系
			List<RoleSQLEntity> roleSqlList = RoleSQLService.getSingleRef().
					getEntityList(RoleSQLEntity.class, new QueryMap());
			// 角色，数据表名称，权限记录
			sqlCache = new HashMap<String, HashMap<String, String>>();
			if (roleSqlList != null && nodeList != null) {
				// 角色ID, 数据权限ID。收集所有的角色和数据功能ID集
				HashMap<String, List<String>> roleFunctionMap = new HashMap<String, List<String>>();
				for (RoleSQLEntity row : roleSqlList) {
					String roleID = row.getRoleID();
					String functionID = row.getFuntionID();
					
					List<String> functionList = null;
					if(roleFunctionMap.containsKey(roleID)){
						functionList = roleFunctionMap.get(roleID);
					}else{
						functionList = new ArrayList<String>();
						roleFunctionMap.put(roleID, functionList);
					}
					if(!functionList.contains(functionID)){
						functionList.add(functionID);
					}
				}
				
				Set<String> roleKeys = roleFunctionMap.keySet();
				for(String roleKey : roleKeys){
					// 角色，所有的功能ID
					List<String> functionList = roleFunctionMap.get(roleKey);
					// tableid, tableWhere
					HashMap<String, String> tableMap = new HashMap<String, String>();
					
					// 第一层，使用and连接，后面层次，使用or连接
					for(TreeDataNode node : nodeList){
						String functionId = node.getid();
						if(functionList.contains(functionId)){
							HashMap<String, String> cTableMap = getTableWhere(node, functionList, functionMap);
							if(cTableMap==null || cTableMap.size()<=0){
								// tableid, tablewhere
								HashMap<String, String> tableWhereMap = functionMap.get(functionId);
								Set<String> tableKeys = tableWhereMap.keySet();
								for(String tableKey : tableKeys){
									if(tableMap.containsKey(tableKey)){
										String tableWhere = "(" + tableMap.get(tableKey) + ") and ( " + tableWhereMap.get(tableKey) + " )";
										tableMap.put(tableKey, tableWhere);
									}else{
										tableMap.put(tableKey, tableWhereMap.get(tableKey));
									}
								}
							}else{
								Set<String> tableKeys = cTableMap.keySet();
								for(String tableKey : tableKeys){
									if(tableMap.containsKey(tableKey)){
										String tableWhere = "(" + tableMap.get(tableKey) + ") and ( " + cTableMap.get(tableKey) + " )";
										tableMap.put(tableKey, tableWhere);
									}else{
										tableMap.put(tableKey, cTableMap.get(tableKey));
									}
								}
							}
						}
					}
					
					sqlCache.put(roleKey, tableMap);
				}
			}
			SafeCache.setRoleSqlCache(sqlCache);
		} catch (Exception e) {
			logger.info("initSQLData 初始化角色数据权限数据失败，原因：" + e.getMessage());
		}
	}

	private static HashMap<String, String> getTableWhere(TreeDataNode pNode, List<String> functionList, 
			HashMap<String, HashMap<String, String>> functionMap){
		List<TreeDataNode> nodeList = pNode.getChildren();
		if(nodeList==null || nodeList.size()<=0){
			return null;
		}
		HashMap<String, String> tableMap = new HashMap<String, String>();
		
		// 第一层，使用and连接，后面层次，使用or连接
		for(TreeDataNode node : nodeList){
			String functionId = node.getid();
			if(functionList.contains(functionId)){
				// tableid, tablewhere
				HashMap<String, String> tableWhereMap = functionMap.get(functionId);
				Set<String> tableKeys = tableWhereMap.keySet();
				for(String tableKey : tableKeys){
					if(tableMap.containsKey(tableKey)){
						String tableWhere = "(" + tableMap.get(tableKey) + ") or ( " + tableWhereMap.get(tableKey) + " )";
						tableMap.put(tableKey, tableWhere);
					}else{
						tableMap.put(tableKey, tableWhereMap.get(tableKey));
					}
				}
			}
			
			getTableWhereEx(node, functionList, functionMap, tableMap);
		}
		return tableMap;
	}
	
	private static void getTableWhereEx(TreeDataNode pNode, List<String> functionList, 
			HashMap<String, HashMap<String, String>> functionMap, HashMap<String, String> tableMap){
		List<TreeDataNode> nodeList = pNode.getChildren();
		if(nodeList==null || nodeList.size()<=0){
			return;
		}
		
		// 第一层，使用and连接，后面层次，使用or连接
		for(TreeDataNode node : nodeList){
			getTableWhereEx(node, functionList, functionMap, tableMap);
			
			String functionId = node.getid();
			if(functionList.contains(functionId)){
				// tableid, tablewhere
				HashMap<String, String> tableWhereMap = functionMap.get(functionId);
				Set<String> tableKeys = tableWhereMap.keySet();
				for(String tableKey : tableKeys){
					if(tableMap.containsKey(tableKey)){
						String tableWhere = "(" + tableMap.get(tableKey) + ") or ( " + tableWhereMap.get(tableKey) + " )";
						tableMap.put(tableKey, tableWhere);
					}else{
						tableMap.put(tableKey, tableWhereMap.get(tableKey));
					}
				}
			}
		}
	}
	
	/**
	 * 初始化角色委托数据
	 */
	private static void initWtData() {
		try {
			HashMap<String, List<String>> wtCache = SafeCache.getRoleWTCache();
			// 如果缓存存在，就说明已经初始过了，不需要再初始化
			if (wtCache != null) {
				return;
			}

			logger.info("initWtData 初始化角色委托数据");
			
			IQueryMap queryMap = new QueryMap();
			queryMap.getWhereMap().put(RoleChangeEntity.FIELD_ISUSE, RoleWtDic.useing);
			List<RowBase> tables = RoleChangeService.getSingleRef().getEntityList(RowBase.class, queryMap);

			// 被委托用户ID，角色ID集
			wtCache = new HashMap<String, List<String>>();
			if (tables != null) {
				for (RowBase row : tables) {
					String bwtUserID = (String) row.getValue(
							GlobalDataType.String,
							RoleChangeEntity.FIELD_I_BWT_USERID);
					String roleID = (String) row.getValue(
							GlobalDataType.String,
							RoleChangeEntity.FIELD_I_ROLEID);

					List<String> wtRoles = null;
					if (wtCache.containsKey(bwtUserID)) {
						wtRoles = wtCache.get(bwtUserID);
					} else {
						wtRoles = new ArrayList<String>();
						wtCache.put(bwtUserID, wtRoles);
					}
					if (!wtRoles.contains(roleID))
						wtRoles.add(roleID);
				}
			}
			SafeCache.setRoleWTCache(wtCache);
		} catch (Exception e) {
			logger.info("initWtData 初始化角色委托数据失败，原因：" + e.getMessage());
		}
	}

	/**
	 * 初始化所有功能数据
	 */
	private static void initFunctionData() {
		try {
			HashMap<String, RowBase> functionCache = SafeCache
					.getFunctionCache();
			HashMap<String, List<RowBase>> roleFunctionCache = SafeCache
					.getRoleFunctionCache();
			// 如果缓存存在，就说明已经初始过了，不需要再初始化
			if (functionCache != null && roleFunctionCache != null) {
				return;
			}

			List<RowBase> tables;
			logger.info("initFunctionData 初始化所有功能数据");
			tables = FunctionService.getSingleRef().getEntityList(
					RowBase.class, new QueryMap());
			// 功能ID，功能Row
			functionCache = new HashMap<String, RowBase>();
			if (tables != null) {
				for (RowBase row : tables) {
					String functionID = (String) row.getValue(
							GlobalDataType.String,
							FunctionEntity.FIELD_FUNCTIONID);
					if (!functionCache.containsKey(functionID)) {
						functionCache.put(functionID, row);
					}
				}
			}
			SafeCache.setFunctionCache(functionCache);

			logger.info("initFunctionData 初始化角色与功能数据");
			tables = RoleFunctionService.getSingleRef().getEntityList(
					RowBase.class, new QueryMap());
			roleFunctionCache = new HashMap<String, List<RowBase>>();
			if (tables != null) {
				for (RowBase row : tables) {
					String roleID = (String) row.getValue(
							GlobalDataType.String,
							RoleFunctionEntity.FIELD_ROLEID);
					List<RowBase> rowList = null;
					if (roleFunctionCache.containsKey(roleID)) {
						rowList = roleFunctionCache.get(roleID);
					} else {
						rowList = new ArrayList<RowBase>();
						roleFunctionCache.put(roleID, rowList);
					}
					rowList.add(row);
				}
			}
			SafeCache.setRoleFunctionCache(roleFunctionCache);
		} catch (Exception e) {
			logger.info("initFunctionData 初始化角色与功能数据失败，原因：" + e.getMessage());
		}
	}

	/**
	 * 根据用户名称，获取用户记录
	 * 
	 * @param userName
	 * @return
	 */
	public static UserEntity getUser(String userName, String orgid) {
		IQueryMap queryMap = new QueryMap();
		queryMap.getWhereMap().put(UserEntity.FIELD_C_USERNAME, userName);
		if(!com.szholly.utils.util.StringUtils.IsNullOrSpace(orgid)
				&& orgid!="-1"){
			if(orgid.endsWith("0000") && orgid.length() == 6){
				queryMap.getWhereMap().put(UserEntity.FIELD_ORGID, orgid);
			}else if(orgid.endsWith("00") && orgid.length() == 6){
				orgid = orgid.substring(0,4);
				queryMap.getWhereMap().put(UserEntity.FIELD_ORGID+":like%", orgid);
			}else{
				queryMap.getWhereMap().put(UserEntity.FIELD_ORGID, orgid);
			}
		}
		UserEntity userEntity = UserService.getSingleRef().getEntity(
				UserEntity.class, queryMap);
		return userEntity;
	}
	
	/**
	 * 根据用户名称，获取用户记录
	 * 
	 * @param userName
	 * @return
	 */
	public static UserEntity getUser(String userName) {
		IQueryMap queryMap = new QueryMap();
		queryMap.getWhereMap().put(UserEntity.FIELD_C_USERNAME, userName);
		UserEntity userEntity = UserService.getSingleRef().getEntity(
				UserEntity.class, queryMap);
		return userEntity;
	}
	
	/**
	 * 根据用户ID获取用户的功能权限
	 * 只获取类型为android的功能标识
	 * 
	 * @param userid
	 */
	public static List<String> getFunctions(String userid) {
		IQueryMap queryMap = new QueryMap();
		queryMap.setSelectFields(UserRoleEntity.FIELD_ROLEID);
		queryMap.getWhereMap().put(UserRoleEntity.FIELD_USERID, userid);
		List<RowBase> result = UserRoleService.getSingleRef().getEntityList(RowBase.class, queryMap);
		if (result == null) {
			return null;
		}
		// 初始化数据
		InitRoleData();

		// 角色，功能集
		HashMap<String, List<RowBase>> roleFunctionCache 
			= SafeCache.getRoleFunctionCache();

		// 功能ID，功能Row
		HashMap<String, RowBase> functionCache = SafeCache.getFunctionCache();
		List<String> functionUrl = new ArrayList<String>();
		List<String> functionTag = new ArrayList<String>();

		for (RowBase row : result) {
			// 获取角色
			String roleID = (String) row.getValue(GlobalDataType.String,
					UserRoleEntity.FIELD_ROLEID);

			// 获取功能权限
			if (roleFunctionCache != null
					&& roleFunctionCache.containsKey(roleID)) {
				List<RowBase> funs = roleFunctionCache.get(roleID);
				for (RowBase urlItem : funs) {
					String functionID = (String) urlItem.getValue(
							GlobalDataType.String,
							RoleFunctionEntity.FIELD_FUNCTIONID);
					if (functionCache.containsKey(functionID)) {
						RowBase functionRow = functionCache.get(functionID);
						String funType = (String) functionRow.getValue(
								GlobalDataType.String,
								FunctionEntity.FIELD_C_FUNCTIONTYPE);
						if(funType.equals("1")){
							getFunction(functionUrl, functionTag, functionRow);
						}
					}
				}
			}
		}

		// 处理委托权限
		// 被委托用户ID，角色ID集
		HashMap<String, List<String>> wtCache = SafeCache.getRoleWTCache();
		if (wtCache != null && wtCache.containsKey(userid)) {
			List<String> roles = wtCache.get(userid);
			for (String roleID : roles) {
				// 获取功能权限
				if (roleFunctionCache != null
						&& roleFunctionCache.containsKey(roleID)) {
					List<RowBase> funs = roleFunctionCache.get(roleID);
					for (RowBase urlItem : funs) {
						String funType = (String) urlItem.getValue(
								GlobalDataType.String,
								FunctionEntity.FIELD_C_FUNCTIONTYPE);
						if(funType.equals("1")){
							getFunction(functionUrl, functionTag, urlItem);
						}
					}
				}
			}
		}

		return functionTag;
	}

	/**
	 * 根据用户ID，将用户属性角色的功能权限，数据权限存储到Session中
	 * 
	 * @param userid
	 */
	public static void getRoles(UserEntity userEntity) {
		// 非超级管理员，处理功能
		if(!userEntity.getIsSuperAdmin()){
			String userid = userEntity.getUserID();
			IQueryMap queryMap = new QueryMap();
			queryMap.setSelectFields(UserRoleEntity.FIELD_ROLEID);
			queryMap.getWhereMap().put(UserRoleEntity.FIELD_USERID, userid);
			List<RowBase> result = UserRoleService.getSingleRef().getEntityList(RowBase.class, queryMap);
			if (result == null) {
				return;
			}
			// 初始化数据
			InitRoleData();

			// 角色，功能集
			HashMap<String, List<RowBase>> roleFunctionCache = SafeCache
					.getRoleFunctionCache();

			// 功能ID，功能Row
			HashMap<String, RowBase> functionCache = SafeCache.getFunctionCache();
			List<String> functionUrl = new ArrayList<String>();
			List<String> functionTag = new ArrayList<String>();

			// 角色，数据表名称，权限记录
			HashMap<String, HashMap<String, String>> sqlCache = SafeCache
					.getRoleSqlCache();
			HashMap<String, String> sqlList = new HashMap<String, String>();

			for (RowBase row : result) {
				// 获取角色
				String roleID = (String) row.getValue(GlobalDataType.String,
						UserRoleEntity.FIELD_ROLEID);

				// 获取功能权限
				if (roleFunctionCache != null
						&& roleFunctionCache.containsKey(roleID)) {
					List<RowBase> funs = roleFunctionCache.get(roleID);
					for (RowBase urlItem : funs) {
						String functionID = (String) urlItem.getValue(
								GlobalDataType.String,
								RoleFunctionEntity.FIELD_FUNCTIONID);
						if (functionCache.containsKey(functionID)) {
							RowBase functionRow = functionCache.get(functionID);
							getFunction(functionUrl, functionTag, functionRow);
						}
					}
				}

				// 获取数据权限
				if (sqlCache != null && sqlCache.containsKey(roleID)) {
					HashMap<String, String> item = sqlCache.get(roleID);
					Set<String> keySet = item.keySet();
					for (String key : keySet) {
						sqlList.put(key, item.get(key));
					}
				}
			}

			// 处理委托权限
			// 被委托用户ID，角色ID集
			HashMap<String, List<String>> wtCache = SafeCache.getRoleWTCache();
			if (wtCache != null && wtCache.containsKey(userid)) {
				List<String> roles = wtCache.get(userid);
				for (String roleID : roles) {
					// 获取功能权限
					if (roleFunctionCache != null
							&& roleFunctionCache.containsKey(roleID)) {
						List<RowBase> funs = roleFunctionCache.get(roleID);
						for (RowBase urlItem : funs) {
							getFunction(functionUrl, functionTag, urlItem);
						}
					}

					// 获取数据权限
					if (sqlCache != null && sqlCache.containsKey(roleID)) {
						HashMap<String, String> item = sqlCache.get(roleID);
						Set<String> keySet = item.keySet();
						for (String key : keySet) {
							sqlList.put(key, item.get(key));
						}
					}
				}
			}

			SessionFactory.getSession().setObject(ISessionProvider.Function, functionTag);
			SessionFactory.getSession().setObject(ISessionProvider.SQLList, sqlList);
			SessionFactory.getSession().setObject(ISessionProvider.FunctionUrl, functionUrl);
		}

		SessionFactory.getSession().setObject(ISessionProvider.UserEntity, userEntity);
		SessionFactory.getSession().setObject(ISessionProvider.UserID, userEntity.getUserID());
		
		SessionFactory.getSession().setObject(ISessionProvider.OrgId, userEntity.getOrgID());
		SessionFactory.getSession().setObject(ISessionProvider.OrgName, userEntity.getOrgName());
		
		SessionFactory.getSession().setObject(ISessionProvider.DeptId, userEntity.getDEPTID());
		SessionFactory.getSession().setObject(ISessionProvider.DeptName, userEntity.getDEPTName());
		
		SessionFactory.getSession().setObject(ISessionProvider.Password, userEntity.getPassword());
		SessionFactory.getSession().setObject(ISessionProvider.UserName, userEntity.getUserName());
		SessionFactory.getSession().setObject(ISessionProvider.UserRealName, userEntity.getUserRealName());
	}

	private static void getFunction(List<String> functionUrl,
			List<String> functionTag, RowBase functionRow) {
		String url = (String) functionRow.getValue(
				GlobalDataType.String,
				FunctionEntity.FIELD_C_FUNCTIONURL);
		if (StringUtils.isNotEmpty(url)) {
			String[] urls = url.split(",");
			for (String item : urls) {
				String urlItem = item.toLowerCase().trim();
				if (!functionUrl.contains(urlItem)) {
					functionUrl.add(urlItem);
				}
			}
		}
		
		String tag = (String) functionRow.getValue(
				GlobalDataType.String,
				FunctionEntity.FIELD_C_FUNCTIONBH);
		if (StringUtils.isNotEmpty(tag)) {
			String[] tags = tag.split(",");
			for (String item : tags) {
				String tagItem = item.toLowerCase().trim();
				if (!functionTag.contains(tagItem)) {
					functionTag.add(tagItem);
				}
			}
		}
	}
}
